package com.apes.autoparts.parts.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.parts.model.AutopartsLog;
import com.apes.autoparts.parts.repository.AutopartsLogRepository;
import com.apes.autoparts.parts.util.FtpUtil;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.esb.processor.connector.http.HttpTransporter;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service("apiAutoParts91Service")
public class ApiAutoParts91Service extends DomainService {

    static private JSONObject authorization = null; // 用户授权

    static private String username = "SY4I5g1AkdkxsHti"; // 用户名

    static private String password = "bVlFxfm6XWfkWCnOIkoxHSzk"; // 密码

    static private String auth = "https://service.91autoparts.com/auth";
    static private String queryVin = "https://service.91autoparts.com/service/epc/vin";
    static private String queryMainGroup = "https://service.91autoparts.com/service/epc/group/main";
    static private String querySubGroup = "https://service.91autoparts.com/service/epc/group/sub";
    static private String queryPartsWithSubGroup = "https://service.91autoparts.com/service/epc/parts";
    static private String queryHotPointsWithSubGroup = "https://service.91autoparts.com/service/epc/hotpoints";

    static private String queryParts = "https://service.91autoparts.com/service/epc/query";
    static private String queryBrandParts = "https://service.91autoparts.com/service/epc/brandautoparts";
    static private String queryPartDetailInfo = "https://service.91autoparts.com/service/epc/part";
    static private String queryPartsSimple = "https://service.91autoparts.com/service/part/simplequery";
    static private String searchParts = "https://service.91autoparts.com/service/epc/parts/search";
    static private String searchbyvinkeywords = "https://service.91autoparts.com/service/epc/parts/searchbyvinkeywords";


    @Autowired
    AutopartsLogRepository autopartsLogRepository;


    /**
     * 获取授权
     *
     * @return
     */
    private JSONObject getAuth() {

        Map param = new HashMap();
        param.put("username", username);
        param.put("password", password);

        authorization = coreRequest(auth, param, new HashMap<>(), "POST");
        return authorization;
    }


    /***
     * 获取vin解析
     */
    public JSONObject parseVin(JSONObject param) {
        JSONObject request = coreRequestGet(queryVin, param);
        return request.getJSONObject("data");
    }




    /***
     * 主组
     * @return
     */
    public JSONArray queryMainGroup(JSONObject param) {
        JSONObject log = new JSONObject();
        Date beginTime =  new Date();
        JSONObject request = coreRequestGet(queryMainGroup, param);
        Date endTime = new Date();
        log.put("request", param);
        log.put("response",request);
        log.put("method", "queryMainGroup");
        log.put("beginTime", beginTime);
        log.put("request", param);
        log.put("endTime", endTime);
        log.put("time", endTime.getTime() - beginTime.getTime());
        this.writerLogging(log);
        JSONArray data = request.getJSONArray("data");
        data.toJavaList(JSONObject.class).stream().forEach(item ->{
            String imageUrl = StringUtil.urlGetFile(item.getString("imageUrl"));
            item.put("imageUrl", imageUrl);
        });

        return request.getJSONArray("data");

    }


    /***
     * 子组
     */

    public JSONArray querySubGroup(JSONObject param) {
        JSONObject log = new JSONObject();
        Date beginTime =  new Date();
        JSONObject request = coreRequestGet(querySubGroup, param);
        Date endTime = new Date();
        log.put("request", param);
        log.put("response",request);
        log.put("method", "querySubGroup");
        log.put("beginTime", beginTime);
        log.put("request", param);
        log.put("endTime", endTime);
        log.put("time", endTime.getTime() - beginTime.getTime());
        this.writerLogging(log);
        JSONArray data = request.getJSONArray("data");
        data.toJavaList(JSONObject.class).stream().forEach(item ->{
            String imageUrl = StringUtil.urlGetFile(item.getString("imageUrl"));
            item.put("imageUrl", imageUrl);
        });
        return request.get("data") != null ? request.getJSONArray("data") : null;
    }

    /***
     * 零件
     */
    public JSONArray queryPartsWithSubGroup(JSONObject param) {
        JSONObject log = new JSONObject();
        Date beginTime =  new Date();
        JSONObject request = coreRequestGet(queryPartsWithSubGroup, param);
        Date endTime = new Date();
        log.put("request", param);
        log.put("response",request);
        log.put("method", "queryParts");
        log.put("beginTime", beginTime);
        log.put("request", param);
        log.put("endTime", endTime);
        log.put("time", endTime.getTime() - beginTime.getTime());
        this.writerLogging(log);
        log.put("invokeMethod", queryPartsWithSubGroup);
        return request.get("data") != null ? request.getJSONArray("data") : null;
    }

    /**
     * 保存图片
     * @param orgImgUrl
     * @return
     */
    public String saveImgToFtp(String orgImgUrl){
        String imgUrl = "";
        String filePath = "";
        String fileName = "";
        String[] split = orgImgUrl.split("/");
        // 子组：
        // https://cdn.91autoparts.com/epc/toyota/200731/160320/865747B.png
        // 切割图片热点图地址
        for (int i = 3; i < split.length; i++) {
            if (i == split.length - 1) {
                fileName = split[i];
                break;
            }
            filePath += "/" + split[i];

        }

        try {

            //new一个URL对象
            URL url = new URL(orgImgUrl);
            URLConnection con = url.openConnection();
            InputStream in = con.getInputStream();

            boolean flag = FtpUtil.uploadFile("10.2.0.16", 21, "yyadmin", "jeKun2020", "/AUTOPARTS",filePath, fileName, in);
            if ( !flag ) {
                return imgUrl;
            }
            imgUrl = "/AUTOPARTS" + filePath + "/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException("图片保存出错:" + e);
        }
        return imgUrl;
    }

    /***
     * 图片热点
     */
    public JSONObject queryHotPointsWithSubGroup(JSONObject param) {
        JSONObject log = new JSONObject();
        Date beginTime =  new Date();
        JSONObject request = coreRequestGet(queryHotPointsWithSubGroup, param);
        Date endTime = new Date();
        log.put("request", param);
        log.put("response",request);
        log.put("method", "queryImgPoint");
        log.put("beginTime", beginTime);
        log.put("endTime", endTime);
        log.put("time", endTime.getTime() - beginTime.getTime());
        log.put("invokeMethod", queryHotPointsWithSubGroup);
        writerLogging(log);
        JSONArray data = request.getJSONObject("data").getJSONArray("imgs");
        data.toJavaList(JSONObject.class).stream().forEach(item ->{
            String imageUrl = StringUtil.urlGetFile(item.getString("url"));
            item.put("url", imageUrl);
        });
        return  request.get("data") != null ? request.getJSONObject("data") : null;
    }


    /**
     * 验证授权的合法性并返回
     *
     * @return JSONObject
     */
    private JSONObject checkAuth() {
        if( authorization == null ||  authorization.getLong(".expires") < (new Date()).getTime()) return getAuth();
        return authorization;
    }


    /***
     * 封装基础查询
     */

    private JSONObject coreRequestGet(String url, Object param) {
        return coreRequest(url, param, "GET");
    }

    private JSONObject coreRequestPost(String url, Object param) {
        return coreRequest(url, param, "POST");
    }

    private JSONObject coreRequest(String url, Object param, String method) {
        JSONObject authorization = checkAuth();

        Map<String, String> header = new HashMap();
        header.put("Authorization", authorization.getString("token_type") + " " + authorization.getString("access_token"));

        return coreRequest(url, param, header, method);
    }

    private JSONObject coreRequest(String url, Object param, Map<String, String> headers, String method) {

        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/x-www-form-urlencoded");
        header.putAll(headers);

        HttpTransporter transporter = new HttpTransporter();
        transporter.setUrl(url);
        transporter.setAction(method);
        transporter.setResponseType("json");
        transporter.setHeaders(headers);

        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        JSONObject response;
        try {
            response = JSONObject.parseObject((String) transporter.process(request));
        } catch (Exception e) {
            e.printStackTrace();
            return response = new JSONObject();
        }

        return handleResponse(response);
//        response = new JSONObject();
//        return response;
    }


    /***
     * 处理返回值
     */
    private JSONObject handleResponse(JSONObject param) {
        if ( "651".equals(param.getString("statusCode")) ) {
            return param;
        }
        if (param.get("statusCode") != null && !param.getString("statusCode").equals("200"))
            throw new RuntimeException("调用接口报错，报错信息：" + param.getString("errorMessage"));
        return param;
    }

    /***
     * 处理 vin 解析报错
     */
    private JSONObject handleParseVin(JSONObject param) {
        JSONObject data = param.getJSONObject("data");
        if (data.getIntValue("resCode") == 1) throw new RuntimeException("不存在对应的vin");
        if (data.getIntValue("resCode") == 2) throw new RuntimeException("权限不足");
        if (data.getIntValue("resCode") == 3) throw new RuntimeException("其他错误");
        return data;
    }

    public JSONObject fuzzyQueryOfParts(JSONObject param) {
        JSONObject request = coreRequestGet(queryParts, param);
        return request;
    }

    public JSONObject queryBrandParts(JSONObject param) {
        JSONObject request = coreRequestGet(queryBrandParts, param);
        return request;
    }

    public JSONObject queryPartsSimple(JSONObject param) {
        JSONObject request = coreRequestGet(queryPartsSimple, param);
        return request;
    }

    public JSONObject searchParts(JSONObject param) {
        JSONObject request = coreRequestGet(searchParts, param);
        return request;
    }

    public JSONObject searchPartsByVinKeywords(JSONObject param) {
        JSONObject log = new JSONObject();
        Date beginTime =  new Date();
        JSONObject request = coreRequestGet(searchbyvinkeywords, param);
        Date endTime = new Date();
        log.put("request", param);
        log.put("response",request);
        log.put("method", "searchPartsByVinKeywords");
        log.put("beginTime", beginTime);
        log.put("endTime", endTime);
        log.put("time", endTime.getTime() - beginTime.getTime());
        log.put("invokeMethod", searchbyvinkeywords);
        writerLogging(log);
        request.getJSONObject("data").getJSONArray("items").toJavaList(JSONObject.class).forEach(item ->{
            item.put("imageUrl", StringUtil.urlGetFile(item.getString("imageUrl")));
        });
        return request;
    }

    //写入日志
    private void writerLogging(JSONObject json) {
        AutopartsLog autopartsLog = new AutopartsLog();
        autopartsLog.setRequest(json.getString("request"));
        autopartsLog.setResponse(json.getString("response"));
        autopartsLog.setName(json.getString("method"));
        autopartsLog.setResponse(json.getJSONObject("response").toString());
        autopartsLog.setRequest(json.getString("request"));
        autopartsLog.setPostId(json.getString("postId"));
        autopartsLog.setPostName(json.getString("postName"));
        autopartsLog.setTime(json.getLong("time"));
        autopartsLog.setBeginTime(json.getDate("beginTime"));
        autopartsLog.setEndTime(json.getDate("endTime"));
        autopartsLogRepository.saveAndFlush(autopartsLog);
    }
    @Listener(topic = "event:writerLogging.message.publish")
    public void consume(SimpleRequest request) {
        AutopartsLog autopartsLog = request.getO(AutopartsLog.class);
        autopartsLogRepository.saveAndFlush(autopartsLog);
    }
}
